package com.kingmed.kmss.bpmn.modules.backup.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kingmed.kmss.bpmn.modules.backup.mapper.BizApprovalStatusMapper;
import com.kingmed.kmss.bpmn.modules.backup.model.BizApprovalStatus;
import com.kingmed.kmss.bpmn.modules.backup.service.BizApprovalStatusService;
import com.kingmed.kmss.bpmn.flow.service.msg.BpmnMsgServiceImpl;
import com.kingmed.kmss.bpmn.flow.utils.OrgUtils;
import com.kingmed.kmss.common.constant.bpmn.ProcessConstant;
import com.kingmed.kmss.common.constant.common.CommonConstants;
import com.kingmed.kmss.common.constant.marketing.MktConstants;
import com.kingmed.kmss.common.utils.DateTimeUtil;
import com.kingmed.kmss.common.utils.StringUtils;
import com.kingmed.kmss.common.vo.CommonPage;
import com.kingmed.kmss.framework.feign.client.admin.CommonAdminFeignServiceFacade;
import com.kingmed.kmss.framework.feign.client.dict.DictFeignServiceFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 * 审批状态表 服务实现类
 * </p>
 *
 * @author wzg
 * @since 2023-02-25
 */
@Service
public class BizApprovalStatusServiceImpl extends ServiceImpl<BizApprovalStatusMapper, BizApprovalStatus> implements BizApprovalStatusService {

	@Autowired
	DictFeignServiceFacade remoteDictSvc;
	@Autowired
	CommonAdminFeignServiceFacade remoteAdminSvc;
	@Autowired
	BpmnMsgServiceImpl msgSvc;

	@Override
	public void saveApprovalStatus(BizApprovalStatus status) {

		log.debug("saveApprovalStatus() Enter: " + status);
		if (status != null && status.getCurrStatus() != null) {
			Map<String, String> statusDictMap = remoteDictSvc.getSysDictMap(CommonConstants.AUDIT_STATUS_DICT);
			String currStatusName = statusDictMap.get(String.valueOf(status.getCurrStatus()));
			status.setCurrStatusName(currStatusName);
		}

		String approvedByName = null;
		if (StringUtils.isNotEmpty(status.getApprovedBy())) {
			approvedByName = remoteAdminSvc.getUserRealName(status.getApprovedBy());
		}
		status.setApprovedByName(approvedByName);

		BizApprovalStatus statusEntity = getApprovalStatus(status.getBizType(), status.getBusinessId(),
				status.getProcInstId());
		if (statusEntity == null) {
			setOrgInfo(status, null);
			save(status);
			return;
		}

		statusEntity.setCurrStatus(status.getCurrStatus());
		statusEntity.setCurrStatusName(status.getCurrStatusName());
		statusEntity.setApprovedBy(status.getApprovedBy());
		statusEntity.setApprovedByName(status.getApprovedByName());
		setOrgInfo(status, statusEntity);

		// 若传了title则保存完整信息
		if (StringUtils.isNotEmpty(status.getBusinessTitle())) {
			statusEntity.setBizKey(status.getBizKey());
			statusEntity.setProcInstId(status.getProcInstId());
			statusEntity.setRequestTime(status.getRequestTime());
			statusEntity.setBusinessTitle(status.getBusinessTitle());
		}

		if (status.getProcessType() != null) {
			statusEntity.setProcessType(status.getProcessType());
		}

		log.debug("saveApprovalStatus() Leave: " + statusEntity);

		updateById(statusEntity);
	}

	private void setOrgInfo(BizApprovalStatus status, BizApprovalStatus statusEntity) {
		String nextApprover = status.getNextApprover();
		if (StringUtils.isNotEmpty(nextApprover)) {
			String nextApproverName = remoteAdminSvc.getUserRealName(nextApprover);
			if (statusEntity == null) {
				status.setNextApproverName(nextApproverName);
				status.setNextApproverDept(OrgUtils.getDeptByUser(nextApprover));
			} else {
				statusEntity.setNextApproverName(nextApproverName);
				statusEntity.setNextApproverDept(OrgUtils.getDeptByUser(nextApprover));
			}
		}

		String requestBy = status.getRequestBy();
		if (StringUtils.isNotEmpty(requestBy)) {
			String requestByName = remoteAdminSvc.getUserRealName(requestBy);
			if (statusEntity == null) {
				status.setRequestBy(requestBy);
				status.setRequestByName(requestByName);
				status.setRequestByDept(OrgUtils.getDeptByUser(requestBy));
			} else {
				statusEntity.setRequestBy(requestBy);
				statusEntity.setRequestByName(requestByName);
				statusEntity.setRequestByDept(OrgUtils.getDeptByUser(requestBy));
			}
		}

		String approvedBy = status.getApprovedBy();
		if (StringUtils.isNotEmpty(approvedBy)) {
			String approvedByName = remoteAdminSvc.getUserRealName(approvedBy);
			if (statusEntity == null) {
				status.setApprovedBy(approvedBy);
				status.setApprovedByName(approvedByName);
				status.setApprovedByDept(OrgUtils.getDeptByUser(approvedBy));
			} else {
				statusEntity.setApprovedBy(approvedBy);
				statusEntity.setApprovedByName(approvedByName);
				statusEntity.setApprovedByDept(OrgUtils.getDeptByUser(approvedBy));
			}
		}
	}

	private BizApprovalStatus getApprovalStatus(String bizType, String businessId, String procInstId) {
		return getBaseMapper().getApprovalStatusByBiz(bizType, businessId, procInstId);
	}

	@Override
	public void updateNextAssignees(String bizType, String bizId, List<String> groupUsers, String procInstId) {
		log.debug("updateNextAssignees: " + bizType + "/" + bizId + "/" + groupUsers);

		if (CollUtil.isEmpty(groupUsers)) {
			return;
		}

		BizApprovalStatus status = getApprovalStatus(bizType, bizId, procInstId);

		if (status == null) {
			status = new BizApprovalStatus();
			status.setBizType(bizType);
			status.setBusinessId(bizId);
		}
		List<String> approverNames = new ArrayList<String>();
		List<String> approvers = new ArrayList<String>();
		groupUsers.forEach(u -> {
			if (StringUtils.isNotEmpty(u)) {
				approvers.add(u);

				String nextApproverName = remoteAdminSvc.getUserRealName(u);
				approverNames.add(nextApproverName);
			}
		});

		status.setNextApprover(String.join(MktConstants.LIST_STRING_SEPERATOR, approvers)+MktConstants.LIST_STRING_SEPERATOR);
		status.setNextApproverName(String.join(MktConstants.LIST_STRING_SEPERATOR, approverNames));

		List<String> depts = new ArrayList<String>();

		groupUsers.forEach(u -> {
			String deptName = OrgUtils.getDeptByUser(u);
			depts.add(deptName);
		});

		status.setNextApproverDept(String.join(",", depts));

		saveOrUpdate(status);

		// 发送系统消息
		msgSvc.send(bizType, bizId, status, groupUsers, procInstId);
	}

	@Override
	public void setApprovedBy(String bizType, String bizId, List<String> groupUsers, String procInstId) {
		log.debug("setApprovedBy: " + bizType + "/" + bizId + "/" + groupUsers);

		if (CollUtil.isEmpty(groupUsers)) {
			return;
		}

		BizApprovalStatus status = getApprovalStatus(bizType, bizId, procInstId);

		if (status == null) {
			status = new BizApprovalStatus();
			status.setBizType(bizType);
			status.setBusinessId(bizId);
		}
		List<String> approverNames = new ArrayList<String>();
		List<String> approvers = new ArrayList<String>();
		groupUsers.forEach(u -> {
			if (StringUtils.isNotEmpty(u)) {
				approvers.add(u);

				String nextApproverName = remoteAdminSvc.getUserRealName(u);
				approverNames.add(nextApproverName);
			}
		});

		status.setApprovedBy(String.join(",", approvers));
		status.setApprovedByName(String.join(",", approverNames));

		if (status.getId() == null) {
			save(status);
		} else {
			updateById(status);
		}
	}

	@Override
	public void saveProcessCompleteStatus(String bizType, String bizId, Boolean approved, String procInstId) {


		BizApprovalStatus status = getApprovalStatus(bizType, bizId, procInstId);
		if (status != null) {
			status.setCurrStatus(approved?ProcessConstant.Status.APPROVED:ProcessConstant.Status.REJECTED);
			Map<String, String> statusDictMap = remoteDictSvc.getSysDictMap(CommonConstants.AUDIT_STATUS_DICT);
			String currStatusName = statusDictMap.get(String.valueOf(status.getCurrStatus()));
			status.setCurrStatusName(currStatusName);

			status.setCompleteTime(new Date());

			// 处理当前处理人为多个人的情况-一般为当前结点审批结束后处理
			if (status.getNextApprover().contains(status.getApprovedBy()+MktConstants.LIST_STRING_SEPERATOR)) {
				status.setNextApprover(status.getApprovedBy());
				status.setNextApproverName(status.getApprovedByName());
			}

		}

		// 永远都有记录。。。
		log.debug("completeProcess: " + status);

		updateById(status);
	}

	@Override
	public CommonPage<BizApprovalStatus> getBizApprovalStatus(String bizType, String approvedByUserId, String currApprover, String auditStatus, int pageSize, int pageNum) {
		Page<BizApprovalStatus> page = new Page<>(pageNum, pageSize);
		QueryWrapper<BizApprovalStatus> wrapper = new QueryWrapper<>();
		LambdaQueryWrapper<BizApprovalStatus> lambda = wrapper.lambda();

		if (StrUtil.isNotEmpty(bizType)) {
			lambda.eq(BizApprovalStatus::getBizType, bizType);
		}
		if (StrUtil.isNotEmpty(approvedByUserId)) {
			lambda.eq(BizApprovalStatus::getApprovedBy, approvedByUserId);
		}

		String currApproverEx = StringUtils.trim(currApprover);
		if (StrUtil.isNotEmpty(currApproverEx)) {
			lambda.like(BizApprovalStatus::getNextApprover, currApproverEx);
		}

		if (StrUtil.isNotEmpty(auditStatus)) {
			lambda.eq(BizApprovalStatus::getCurrStatus, auditStatus);
		}

		lambda.orderByDesc(BizApprovalStatus::getRequestTime);
		Page<BizApprovalStatus> result = page(page, wrapper);


		return CommonPage.restPage(result);
	}

	@Override
	public Page<BizApprovalStatus> getBizApprovalStatusByBizIds(String bizType, List<String> procInstIds,
			String currApprover, String auditStatus, String userId, int pageSize, int pageNum,String startTime, String endTime,String requestByName) {
		Page<BizApprovalStatus> page = new Page<>(pageNum, pageSize);
		QueryWrapper<BizApprovalStatus> wrapper = new QueryWrapper<>();
		LambdaQueryWrapper<BizApprovalStatus> lambda = wrapper.lambda();

		if (StrUtil.isNotEmpty(bizType)) {
			lambda.eq(BizApprovalStatus::getBizType, bizType);
		}

		if (StrUtil.isNotEmpty(requestByName)) {
			lambda.like(BizApprovalStatus::getRequestByName, requestByName);
		}
		if (StrUtil.isNotEmpty(userId)) {
			lambda.like(BizApprovalStatus::getNextApprover, userId+",");
		}

        if (StrUtil.isNotEmpty(startTime)) {
            lambda.ge(BizApprovalStatus::getRequestTime, DateTimeUtil.stringToDate(startTime));
        }
        if (StrUtil.isNotEmpty(endTime)) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(DateTimeUtil.stringToDate(endTime));
            calendar.add(Calendar.DATE, 1);
			lambda.le(BizApprovalStatus::getRequestTime, calendar.getTime());
        }

		String currApproverEx = StringUtils.trim(currApprover);
		if (StrUtil.isNotEmpty(currApproverEx)) {
			lambda.like(BizApprovalStatus::getNextApproverName, currApproverEx);
		}

		if (StrUtil.isNotEmpty(auditStatus)) {
			lambda.eq(BizApprovalStatus::getCurrStatus, auditStatus);
		}

		if (CollUtil.isNotEmpty(procInstIds)) {
			lambda.in(BizApprovalStatus::getProcInstId, procInstIds);
		}
		lambda.orderByDesc(BizApprovalStatus::getRequestTime);
		Page<BizApprovalStatus> result = page(page, wrapper);

		return result;
	}

	@Override
	public BizApprovalStatus getApprovalStatusByTypeAndId(String businessType, String businessId, String procInstId) {

		QueryWrapper<BizApprovalStatus> wrapper = new QueryWrapper<>();
		LambdaQueryWrapper<BizApprovalStatus> lambda = wrapper.lambda();

		if (StrUtil.isNotEmpty(businessType)) {
			lambda.eq(BizApprovalStatus::getBizType, businessType);
		}
		if (StrUtil.isNotEmpty(businessType)) {
			lambda.eq(BizApprovalStatus::getBusinessId, businessId);
		}
		if (StrUtil.isNotEmpty(procInstId)) {
			lambda.eq(BizApprovalStatus::getProcInstId, procInstId);
		}
		return this.getOne(wrapper);
	}

    @Override
    public BizApprovalStatus getByProcessInstanceId(String processInstanceId) {
        return super.getOne(new LambdaQueryWrapper<BizApprovalStatus>().eq(BizApprovalStatus::getProcInstId, processInstanceId).last(CommonConstants.LIMIT_ONE));
    }

    @Override
    public List<BizApprovalStatus> listByBusinessId(String businessId, String businessType) {
		return super.list(new LambdaQueryWrapper<BizApprovalStatus>()
                .eq(BizApprovalStatus::getBusinessId,businessId)
                .eq(BizApprovalStatus::getBizType,businessType)
                .orderByDesc(BizApprovalStatus::getId)
        );
    }


}
